package com.eaglefly.redis.autoconfigure;

import com.eaglefly.redis.scan.ClassPathDaoScanner;
import com.eaglefly.redis.scan.DaoFactoryBean;
import com.github.trang.redisson.autoconfigure.RedissonAutoConfiguration;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import java.util.List;

/**
 * 功能：自动配置redisDao
 * 时间：2018/1/10 17:20
 *
 * @author zhaojinpeng
 */
@Configuration
@ConditionalOnClass(Redisson.class)
@ConditionalOnBean({RedissonClient.class})
@ConditionalOnProperty(prefix = "spring.redissonDao", name = "autoConfig", havingValue = "true")
@AutoConfigureAfter({RedissonAutoConfiguration.class})
@EnableConfigurationProperties(RedissonDaoProperties.class)
public class RedissonDaoAutoConfigure {

    private final static Logger logger = LoggerFactory.getLogger(RedissonDaoAutoConfigure.class);

    private RedissonDaoProperties redissonDaoProperties;

    public static class AutoConfiguredDaoScannerRegistrar
            implements BeanFactoryAware, ImportBeanDefinitionRegistrar, ResourceLoaderAware {

        private BeanFactory beanFactory;

        private ResourceLoader resourceLoader;

        @Override
        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

            logger.debug("Searching for mappers annotated with @RDao");

            ClassPathDaoScanner scanner = new ClassPathDaoScanner(registry);

            try {
                if (this.resourceLoader != null) {
                    scanner.setResourceLoader(this.resourceLoader);
                }

                List<String> packages = AutoConfigurationPackages.get(this.beanFactory);
                if (logger.isDebugEnabled()) {
                    for (String pkg : packages) {
                        logger.debug("Using auto-configuration base package '{}'", pkg);
                    }
                }

                scanner.registerFilters();
                scanner.scan(StringUtils.toStringArray(packages));

            } catch (IllegalStateException ex) {
                logger.debug("Could not determine auto-configuration package, automatic mapper scanning disabled.", ex);
            }

        }

        @Override
        public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
            this.beanFactory = beanFactory;
        }

        @Override
        public void setResourceLoader(ResourceLoader resourceLoader) {
            this.resourceLoader = resourceLoader;
        }
    }


    @Configuration
    @Import({AutoConfiguredDaoScannerRegistrar.class})
    @ConditionalOnMissingBean(DaoFactoryBean.class)
    public static class MapperScannerRegistrarNotFoundConfiguration {

        @PostConstruct
        public void afterPropertiesSet() {
            logger.debug("No {} found.", DaoFactoryBean.class.getName());
        }
    }
}

